feat(images): add image attachment support#97
Merged
Conversation
Add first-class image attachments to the interactive chat TUI. Users can attach images by pasting or drag-dropping local image paths into the prompt, and by pasting clipboard images through terminal-delivered paste input. Clipboard images are materialized to an app-specific directory under `os.tmpdir()` and then treated like normal file attachments. Message and persistence: - Extend `src/utils/ollama.ts` `Message` with `images?: string[]`. - Pass `images` through unchanged to Ollama chat requests. - Preserve `images` in session JSONL persistence and reload them on resume. Attachment model: - Add staged attachment state to chat input, separate from plain text. - On submit, send one user message with: - `content`: typed text only - `images`: absolute image paths for staged attachments - Clear staged attachments after successful submit. Input UX: - Do not add an `/image` command. - Render attachments inline as bracketed atomic tokens using filenames: - real files: `[diagram.png]` - clipboard images: `[image-1.png]`, `[image-2.png]` - Use a dedicated attachment color distinct from normal prompt text. - Keep the cursor outside token internals; left/right moves across each token as one unit. - `Backspace`/`Delete` removes an adjacent token as a whole. - Normal typed text remains editable after the attachment tokens. Attachment ingestion: - Detect pasted or drag-dropped local image paths in the prompt and stage them as attachments instead of leaving them as plain text. - If pasted text is not a valid readable image path, keep it as ordinary text. - Add clipboard-image ingestion through paste/key handling where the terminal exposes it. - Materialize clipboard images to `path.join(os.tmpdir(), 'code-ollama', 'images')` with generated names like `image-1.png`. - Keep user-supplied file attachments at their original paths; only clipboard images are copied to temp storage. Rendering history: - Show sent user attachments in message history using the same bracketed filename convention. - Do not attempt inline bitmap previews in the terminal. Public Interface Changes: - `Message` gains optional `images?: string[]`. - `TextInput`/`ChatInput` move from string-only editing to structured input with attachment tokens plus text. - Add an internal clipboard utility that reads a clipboard image and writes it to the app temp image directory. Test Plan: - `utils/ollama` tests: messages with `images` are forwarded to Ollama. - Session tests: messages with `images` persist and reload correctly. - Chat input tests: - valid image paths stage attachments - invalid paths remain plain text - multiple attachments render as bracketed filename tokens - token navigation is atomic - backspace/delete removes whole tokens - normal text editing still works - Clipboard tests: - clipboard image ingestion writes to the temp image directory and stages the resulting file - generated names follow `image-N.ext` - empty/unavailable clipboard produces a user-facing error - Submit/render tests: - submitting text plus attachments sends `content` and `images` - staged attachments clear after submit - history renders bracketed attachment filenames consistently - Regression tests: - slash command flow - `@` file suggestion flow - prompt history navigation Assumptions and Defaults: - Scope is TUI chat only; the one-off `run` command remains unchanged. - Attachment tokens always render with brackets and a distinct color. - Clipboard-derived images are stored under `os.tmpdir()` in an app-specific subdirectory. - If a staged clipboard image is removed before send, its temp file should be deleted. - Sent clipboard image temp files are retained in v1 so resumed sessions can still reference them as long as the OS has not cleaned temp storage. - Model capability checks are not enforced in the UI; unsupported image behavior is left to Ollama/model responses.
Codecov Report✅ All modified and coverable lines are covered by tests.
🚀 New features to boost your workflow:
|
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
5ecf20e to
116e4ed
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the motivation for this pull request?
Feature: Add image attachment support to the TUI chat interface, allowing users to attach and send images alongside text prompts to multimodal models.
What is the current behavior?
The TUI chat only supports text prompts. Users cannot attach images or other files to their messages.
What is the new behavior?
plan.md
Checklist: